#include "../include/CSDLManager.h"

#include <assert.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

//**************************
//Description : Constructor
//Parameters : None
//Note : Private because a single instance is needed
//**************************
CSDLManager::CSDLManager()
{
}

//**************************
//Description : Destructor
//Parameters : None
//Note : None
//**************************
CSDLManager::~CSDLManager()
{
}

//**************************
//Description : Init the instance
//Parameters : None
//Return Value : None
//Note : None
//**************************
void CSDLManager::Init()
{
	int iInitError = SDL_Init(SDL_INIT_VIDEO);
    assert( iInitError != -1 );

	iInitError = TTF_Init();
    assert ( iInitError != -1 );

    m_Screen = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_HWSURFACE);

    assert( m_Screen != NULL );

    LoadSurfaces();
}

//**************************
//Description : DeInit the instance
//Parameters : None
//Return Value : None
//Note : None
//**************************
void CSDLManager::DeInit()
{
    for ( int i = 0; i < MAX_PLAYERS; i++ )
    {
        if ( m_vPlayerAnimations[i] != NULL )
            delete[] m_vPlayerAnimations[i];

        if ( m_vPlayerShotsAnimations[i] != NULL )
            delete[] m_vPlayerShotsAnimations[i];
    }

    for ( int i = 0; i < NUMBER_ENEMIES; i++ )
    {
        if ( m_vEnemyAnimations[i] != NULL )
            delete[] m_vEnemyAnimations[i];

        if ( m_vEnemyShotsAnimations[i] != NULL )
            delete[] m_vEnemyShotsAnimations[i];
    }

    for ( int i = 0; i < NUMBER_POWERUP; i++ )
    {
        if ( m_vPowerUpAnimations[i] != NULL )
            delete m_vPowerUpAnimations[i];
    }

    if ( m_BackGroundMenu != NULL )
    {
        SDL_FreeSurface(m_BackGroundMenu);
    }

    if ( m_GameTitle != NULL )
    {
        SDL_FreeSurface(m_GameTitle);
    }

    if ( m_Menu != NULL )
    {
        for (int i = 0; i < (NUMBER_OPTION_MENU*2); i++)
            SDL_FreeSurface(m_Menu[i]);
    }

    if ( m_Highscore_Menu != NULL )
    {
        SDL_FreeSurface(m_Highscore_Menu);
    }

    if ( m_Highscores_Game != NULL )
    {
        for (int i = 0; i < (MAX_PLAYERS+1); i++)
            SDL_FreeSurface(m_Highscores_Game[i]);
    }

    if ( m_Lives != NULL )
    {
        for (int i = 0; i < MAX_PLAYERS; i++)
            SDL_FreeSurface(m_Lives[i]);
    }

    if ( m_Numbers != NULL )
    {
        for (int i = 0; i < 10; i++)
            SDL_FreeSurface(m_Numbers[i]);
    }

    if ( m_BigGameFont != NULL )
    {
        TTF_CloseFont(m_BigGameFont);
    }

    if ( m_LittleGameFont != NULL )
    {
        TTF_CloseFont(m_LittleGameFont);
    }

    SDL_FreeSurface(m_Screen);
    TTF_Quit();
    SDL_Quit();
}

//**************************
//Description : Load the Surfaces needed by the game (player, enemies, shots, font, ...)
//Parameters : None
//Return Value : true if success, otherwise false
//Note : None
//**************************
bool CSDLManager::LoadSurfaces()
{
    std::string szDir(szSurfacesDir);

    //we load the font
    szDir.clear();
    szDir = szSurfacesDir;

    szDir += "courbi.ttf";

    m_BigGameFont = TTF_OpenFont( szDir.c_str(), 65);

    assert( m_BigGameFont != NULL );

    m_LittleGameFont = TTF_OpenFont( szDir.c_str(), 35);

    assert( m_LittleGameFont != NULL );

    //this variable will allow us to put number in a string
    char szNum[4];
    //this  variable will be the temporary variable for SDL_Surface before adapting to the correct format
    SDL_Surface * tmp;

    //we load the background menu
    szDir.clear();
    szDir = szSurfacesDir;

    szDir += "background_menu.jpg";

    tmp = IMG_Load( szDir.c_str() );
    assert( tmp != NULL );

    m_BackGroundMenu = SDL_DisplayFormat(tmp);

    //we load the game title
    szDir.clear();
    szDir = szSurfacesDir;

    szDir += "Createmup.bmp";
    tmp = IMG_Load( szDir.c_str() );
    assert( tmp != NULL );

    SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

    m_GameTitle = SDL_DisplayFormat(tmp);

    //we load the menu
    for (int i = 0; i < (NUMBER_OPTION_MENU*2); i++)
    {
        szDir.clear();
        szDir = szSurfacesDir;

        szDir += szMenuDir[i/2];

        if ( i % 2 != 0)
            szDir += "_nonselect.bmp";
        else
            szDir += "_select.bmp";

        tmp = IMG_Load( szDir.c_str() );
        assert( tmp != NULL );

        SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

        m_Menu[i] = SDL_DisplayFormat(tmp);
    }

    //we load the highscore in the menu
    szDir.clear();
    szDir = szSurfacesDir;

    szDir += "highscore_menu.bmp";
    tmp = IMG_Load( szDir.c_str() );
    assert( tmp != NULL );

    SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

    m_Highscore_Menu = SDL_DisplayFormat(tmp);

    //we load the numbers
    for (int i = 0; i < 10; i++)
    {
        szDir.clear();
        szDir = szSurfacesDir;

        sprintf(szNum, "%d", i);
        szDir += szNum;
        szDir += ".bmp";

        tmp = IMG_Load( szDir.c_str() );
        assert( tmp != NULL );

        SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

        m_Numbers[i] = SDL_DisplayFormat(tmp);
    }

    //the first highscore don't have number in its name
    szDir.clear();
    szDir = szSurfacesDir;

    szDir += "highscore_game.bmp";

    tmp = IMG_Load( szDir.c_str() );
    assert( tmp != NULL );

    SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

    m_Highscores_Game[0] = SDL_DisplayFormat(tmp);

    //we load the higschores
    for (int i = 1; i < (MAX_PLAYERS+1); i++)
    {
        szDir.clear();
        szDir = szSurfacesDir;

        szDir += "highscore";
        sprintf(szNum, "%d", i);
        szDir += szNum;
        szDir += ".bmp";

        tmp = IMG_Load( szDir.c_str() );
        assert( tmp != NULL );

        SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

        m_Highscores_Game[i] = SDL_DisplayFormat(tmp);
    }

    //we load the lives
    for (int i = 1; i <= MAX_PLAYERS; i++)
    {
        szDir.clear();
        szDir = szSurfacesDir;

        szDir += "lives";
        sprintf(szNum, "%d", i);
        szDir += szNum;
        szDir += ".bmp";

        tmp = IMG_Load( szDir.c_str() );
        assert( tmp != NULL );

        SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, SDL_MapRGB(tmp->format, 0, 0, 0));

        m_Lives[i-1] = SDL_DisplayFormat(tmp);
    }

    //we create all the surfaces needed for the game (without backgrounds, because background change at each level

    //we load the animations for the player
    for ( int i = 0; i < MAX_PLAYERS; i++ )
    {
        szDir.clear();
        szDir = szPlayerDir[i];

        m_vPlayerAnimations[i] = new CSpriteAnimation[NUMBER_STATES];
        m_vPlayerShotsAnimations[i] = new CSpriteAnimation[NUMBER_SHOTS];

        for ( int j = 0; j < NUMBER_STATES; j++ )
        {
            szDir += szStateDir[j];

            m_vPlayerAnimations[i][j].InitAnimation( szDir.c_str() );

            szDir.clear();
            szDir = szPlayerDir[i];
        }

        for ( int j = 0; j < NUMBER_SHOTS; j++ )
        {
            szDir += szShotDir[j];

            m_vPlayerShotsAnimations[i][j].InitAnimation( szDir.c_str() );

            szDir.clear();
            szDir = szPlayerDir[i];
        }
    }

    //we load the animations for the enemies
    for ( int i = 0; i < NUMBER_ENEMIES; i++ )
    {
        szDir.clear();
        szDir = szEnemyDir[i];

        m_vEnemyAnimations[i] = new CSpriteAnimation[NUMBER_STATES];
        m_vEnemyShotsAnimations[i] = new CSpriteAnimation[NUMBER_SHOTS];

        for ( int j = 0; j < NUMBER_STATES; j++ )
        {
            szDir += szStateDir[j];

            m_vEnemyAnimations[i][j].InitAnimation( szDir.c_str() );

            szDir.clear();
            szDir = szEnemyDir[i];
        }

        for ( int j = 0; j < NUMBER_SHOTS; j++ )
        {
            szDir += szShotDir[j];

            m_vEnemyShotsAnimations[i][j].InitAnimation( szDir.c_str() );

            szDir.clear();
            szDir = szEnemyDir[i];
        }
    }

    //we load the animations for the power up
    for ( int i = 0; i < NUMBER_POWERUP; i++ )
    {
        szDir.clear();
        szDir = szPowerUpDir;

        m_vPowerUpAnimations[i] = new CSpriteAnimation;

        szDir += szTypePowerUpDir[i];

        m_vPowerUpAnimations[i]->InitAnimation( szDir.c_str() );

        szDir.clear();
        szDir = szPowerUpDir;
    }

	return true;
}

//**************************
//Description : Return the tab of animations for the player
//Parameters : the player
//Return Value : tab of animations
//Note : None
//**************************
CSpriteAnimation* CSDLManager::GetPlayerAnimations(int _iNumPlayer)
{
    if ( m_vPlayerAnimations != NULL && _iNumPlayer >= 0 && _iNumPlayer < MAX_PLAYERS )
        return ( m_vPlayerAnimations[_iNumPlayer] );
    else
        return NULL;
}

//**************************
//Description : Return the tab of animations for the player shots
//Parameters : the player
//Return Value : tab of animations
//Note : None
//**************************
CSpriteAnimation* CSDLManager::GetPlayerShotsAnimation(int _iNumPlayer)
{
    if ( m_vPlayerShotsAnimations != NULL && _iNumPlayer >= 0 && _iNumPlayer < MAX_PLAYERS )
        return ( m_vPlayerShotsAnimations[_iNumPlayer] );
    else
        return NULL;
}

//**************************
//Description : Return the tab of animations for the enemy
//Parameters : the enemy
//Return Value : tab of animations
//Note : None
//**************************
CSpriteAnimation* CSDLManager::GetEnemyAnimations(int _iNumEnemy)
{
    if ( m_vEnemyAnimations != NULL && _iNumEnemy >= 0 && _iNumEnemy < NUMBER_ENEMIES )
        return ( m_vEnemyAnimations[_iNumEnemy] );
    else
        return NULL;
}

//**************************
//Description : Return the tab of animations for the enemy shots
//Parameters : the enemy
//Return Value : tab of animations
//Note : None
//**************************
CSpriteAnimation* CSDLManager::GetEnemyShotsAnimation(int _iNumEnemy)
{
    if ( m_vEnemyShotsAnimations != NULL && _iNumEnemy >= 0 && _iNumEnemy < NUMBER_ENEMIES )
        return ( m_vEnemyShotsAnimations[_iNumEnemy] );
    else
        return NULL;
}

//**************************
//Description : Return the tab of animations for the powerups
//Parameters : the type of power up
//Return Value : tab of animations
//Note : None
//**************************
CSpriteAnimation* CSDLManager::GetPowerUpAnimations(int _iNumPowerUp)
{
    if ( m_vPowerUpAnimations != NULL && _iNumPowerUp >= 0 && _iNumPowerUp < NUMBER_POWERUP )
        return ( m_vPowerUpAnimations[_iNumPowerUp] );
    else
        return NULL;
}

//**************************
//Description : Return the surface of the background menu
//Parameters : None
//Return Value : surface of the background
//Note : None
//**************************
SDL_Surface* CSDLManager::GetBackgroundMenu()
{
    return m_BackGroundMenu;
}

//**************************
//Description : Return the surface for the title
//Parameters : the surface for the title
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface* CSDLManager::GetTitleSurface()
{
    return m_GameTitle;
}

//**************************
//Description : Return the surfaces for the menu
//Parameters : the surfaces for the menu
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface** CSDLManager::GetMenuSurfaces()
{
    return m_Menu;
}

//**************************
//Description : Return the surfaces for the highscore in the menu
//Parameters : the surface for the highscore in the menu
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface* CSDLManager::GetHighscoreMenuSurfaces()
{
    return m_Highscore_Menu;
}

//**************************
//Description : Return the surfaces for the highscore in the game
//Parameters : the surface for the highscore in the game
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface** CSDLManager::GetHighscoreGameSurfaces()
{
    return m_Highscores_Game;
}

//**************************
//Description : Return the surfaces for the lives
//Parameters : the surface for the lives
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface** CSDLManager::GetLivesSurfaces()
{
    return m_Lives;
}

//**************************
//Description : Return the surfaces for the numbers
//Parameters : the surface for the numbers
//Return Value : tab of animations
//Note : None
//**************************
SDL_Surface** CSDLManager::GetNumbersSurfaces()
{
    return m_Numbers;
}

//**************************
//Description : Return the big font of the game
//Parameters : None
//Return Value : the font
//Note : None
//**************************
TTF_Font* CSDLManager::GetBigGameFont()
{
    return m_BigGameFont;
}

//**************************
//Description : Return the little font of the game
//Parameters : None
//Return Value : the font
//Note : None
//**************************
TTF_Font* CSDLManager::GetLittleGameFont()
{
    return m_LittleGameFont;
}

//**************************
//Description : Return the screen of the application
//Parameters : None
//Return Value : the screen
//Note : None
//**************************
SDL_Surface* CSDLManager::GetScreen()
{
    return m_Screen;
}

//**************************
//Description : Flip the screen
//Parameters : None
//Return Value : None
//Note : None
//**************************
void CSDLManager::Flip()
{
    SDL_Flip(m_Screen);
}
